package com.topscomm.pm.script;

import com.topscomm.basic.exception.BusinessException;
import com.topscomm.cbo.pojo.CboApprovalNodeInsEntity;
import com.topscomm.cbo.pojo.CboAttachmentEntity;
import com.topscomm.cbo.service.impl.CboAttachmentService;
import com.topscomm.pm.PmScript;
import com.topscomm.pm.PmSystemConst;
import com.topscomm.pm.pojo.PmInvoiceApplyEntity;
import com.topscomm.pm.service.impl.PmCustomerService;
import com.topscomm.pm.service.impl.PmInvoiceApplyService;
import com.topscomm.pm.service.impl.PmInvoiceRecordService;
import com.topscomm.pub.util.ConvertUtil;
import com.topscomm.pub.util.SpringUtil;
import com.topscomm.pub.util.StringBufferProxy;
import com.topscomm.pub.util.StringUtil;
import com.topscomm.tap.ITapService;
import com.topscomm.tap.TapEntity;
import com.topscomm.tap.common.DatacodeCache;
import com.topscomm.tap.common.ParameterCache;
import org.apache.commons.collections4.map.HashedMap;
import org.springframework.http.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.*;

public class PmInvoiceScript extends PmScript {
    /**
     * @author: wushenghong
     * @date: 2020/6/4
     * @description: 项目开票金额更新
     */
    @Transactional
    public void updateBillMoneyToProject(ITapService service, TapEntity entity) throws Exception {
        // 审批节点实例
        CboApprovalNodeInsEntity nodeIns = (CboApprovalNodeInsEntity) entity;
        String sourceId = ConvertUtil.convertToString(nodeIns.getSourceid());
        PmInvoiceApplyService pmInvoiceApplyService = (PmInvoiceApplyService) SpringUtil.getBean("pmInvoiceApplyService");
        pmInvoiceApplyService.updateBillMoneyOfProjectBase(sourceId, true);
        // 作废申请
        PmInvoiceApplyEntity pmInvoiceApplyEntity = pmInvoiceApplyService.queryById(sourceId);
        if (pmInvoiceApplyEntity != null) {
            if (!("1".equals(pmInvoiceApplyEntity.getCategory()))) {
                Long oldId = pmInvoiceApplyEntity.getOldid();
                Map<String, Object> updateParam = new HashedMap<>();
                updateParam.put("id", oldId);
                updateParam.put("iscancel", '1');
                pmInvoiceApplyService.update(updateParam);
            }
        }
    }

    /**
     * @author: wushenghong
     * @date: 2020/7/13
     * @description: 客户档案erp编号回写
     */
    public void updateErpCodeToCustomer(ITapService service, TapEntity entity) throws Exception {
        // 审批节点实例
        CboApprovalNodeInsEntity nodeIns = (CboApprovalNodeInsEntity) entity;
        String sourceId = ConvertUtil.convertToString(nodeIns.getSourceid());
        PmInvoiceApplyService pmInvoiceApplyService = (PmInvoiceApplyService) SpringUtil.getBean("pmInvoiceApplyService");
        PmCustomerService pmCustomerService = (PmCustomerService) SpringUtil.getBean("pmCustomerService");
        // 作废申请
        PmInvoiceApplyEntity pmInvoiceApplyEntity = pmInvoiceApplyService.queryById(sourceId);
        if (pmInvoiceApplyEntity != null) {
            if (!("2".equals(pmInvoiceApplyEntity.getCategory()))) {// 新增或重开
                Long customerId = pmInvoiceApplyEntity.getCustomerid();
                Map<String, Object> updateParam = new HashedMap<>();
                updateParam.put("id", customerId);
                updateParam.put("erpcode", pmInvoiceApplyEntity.getErpcode());
                pmCustomerService.update(updateParam);
            }
        }
    }


    /**
     * @return
     * @author: shenyouyi
     * @date: 2020-09-22
     * @description: 将发票申请单推送给销售开票平台
     * @modify:
     */
    @Transactional
    public void syncInvoiceApplyToInvoiceSystem(ITapService service, TapEntity entity) throws Exception {
        // 审批节点实例
        CboApprovalNodeInsEntity nodeIns = (CboApprovalNodeInsEntity) entity;
        String sourceId = ConvertUtil.convertToString(nodeIns.getSourceid());
        PmInvoiceApplyService pmInvoiceApplyService = (PmInvoiceApplyService) SpringUtil.getBean("pmInvoiceApplyService");
        PmInvoiceApplyEntity pmInvoiceApplyEntity = pmInvoiceApplyService.queryById(sourceId);
        String invoiceSystemUrl = ParameterCache.getValue("PmInvoiceSystemServerUrl");
        String appkey = ParameterCache.getValue("PmInvoiceSystemAppkey");
        RestTemplate restTemplate = (RestTemplate) SpringUtil.getBean("restTemplate");
        String url = invoiceSystemUrl + "/sync?appkey=" + appkey;
        //设置请求头
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Type", MediaType.APPLICATION_JSON_UTF8_VALUE);
        //设置请求参数
        Map<String, Object> postData = this.initInvoiceSysParaMap(pmInvoiceApplyEntity);
        HttpEntity httpEntity = new HttpEntity(postData, httpHeaders);
        ResponseEntity<Map> responseEntity = restTemplate.postForEntity(url, httpEntity, Map.class);
        // 如果失败，抛出异常，如果成功，则上传附件
        if (responseEntity.getStatusCode().equals(HttpStatus.OK)) {
            if((boolean) responseEntity.getBody().get("success")){
                this.uploadAttachment(pmInvoiceApplyEntity);
            } else {
                String message =  ConvertUtil.convertToString(responseEntity.getBody().get("message"));
                if(StringUtil.isEmpty(message)){
                    message = "同步到发票平台失败";
                }
                throw new BusinessException(message);
            }
        } else {
            throw new BusinessException("同步到发票平台失败");
        }
    }

    /**
     * @return
     * @author: shenyouyi
     * @date: 2020-09-23
     * @param: pmInvoiceApplyEntity
     * @description: 上传附件
     * @modify:
     */
    private void uploadAttachment(PmInvoiceApplyEntity pmInvoiceApplyEntity) {
        CboAttachmentService cboAttachmentService = (CboAttachmentService) SpringUtil.getBean("cboAttachmentService");
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle(CboAttachmentEntity.FieldSourcetype + "= {0} and " + CboAttachmentEntity.FieldSourceid + " = {1}", "'PmInvoiceApply'", pmInvoiceApplyEntity.getId());
        List<CboAttachmentEntity> cboAttachmentEntities = cboAttachmentService.queryByWhere(sql.toString());
        Map<String, Object> paraMap = new HashMap<>();
        String invoiceSystemUrl = ParameterCache.getValue("PmInvoiceSystemServerUrl");
        String appkey = ParameterCache.getValue("PmInvoiceSystemAppkey");
        RestTemplate restTemplate = (RestTemplate) SpringUtil.getBean("restTemplate");
        String url = invoiceSystemUrl + "/addAttachment?appkey=" + appkey;
        //设置请求头
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Type", MediaType.APPLICATION_JSON_UTF8_VALUE);
        for (CboAttachmentEntity cboAttachmentEntity : cboAttachmentEntities) {
            paraMap.clear();
            paraMap.put("attachmentId", cboAttachmentEntity.getId());
            Map<String, Object> resultMap = cboAttachmentService.executeDownload(paraMap);
            String attFileName = (String) resultMap.get("attFileName");
            byte[] fileDataArray = (byte[]) resultMap.get("attInputStream");
            String fileData = Base64.getEncoder().encodeToString(fileDataArray);
            paraMap.clear();
            paraMap.put("sourceapp", "PM");
            paraMap.put("sourcetype", "项目开票");
            // souceid 传 docno
            paraMap.put("sourceid", pmInvoiceApplyEntity.getDocno());
            paraMap.put("fileName", attFileName);
            paraMap.put("fileData", fileData);
            //设置请求参数
            HttpEntity httpEntity = new HttpEntity(paraMap, httpHeaders);
            ResponseEntity<Map> responseEntity = restTemplate.postForEntity(url, httpEntity, Map.class);
            // 如果失败，抛出异常
            if (!responseEntity.getStatusCode().equals(HttpStatus.OK) || !(boolean) responseEntity.getBody().get("success")) {
                throw new BusinessException("同步到发票平台失败");
            }
        }
    }

    /**
     * @return
     * @author: shenyouyi
     * @date: 2020-09-22
     * @param: pmInvoiceApplyEntity
     * @description: 初始化发票系统参数
     * @modify:
     */
    private Map<String, Object> initInvoiceSysParaMap(PmInvoiceApplyEntity pmInvoiceApplyEntity) {
        Map<String, Object> postData = new HashMap<>();
        postData.put("sourceapp", "PM");
        postData.put("sourcetype", "项目开票");
        // sourceid 传 docno
        // postData.put("sourceid", String.valueOf(pmInvoiceApplyEntity.getId()));
        postData.put("sourceid", pmInvoiceApplyEntity.getDocno());
        postData.put("categorycode", "1");// 发票
        postData.put("createtype", "0");// 蓝字发票
        String invoicetype = pmInvoiceApplyEntity.getInvoicetype();
        DatacodeCache datacodeCache = (DatacodeCache) SpringUtil.getBean("datacodeCache");
        String invoicetypeDesc = datacodeCache.getValueDynamic("PmInvoiceType", invoicetype, "code", "name");
        if (invoicetypeDesc.contains("专用发票")) {// 专票
            postData.put("billtype", "0");
        } else if (invoicetypeDesc.contains("普通发票")) {// 普票
            postData.put("billtype", "2");
        }
        Map<String, Object> deviceCondition = new HashMap<>();
        deviceCondition.put("billtype", "蓝票");
        if ("D1".equals(pmInvoiceApplyEntity.getInvoiceorgcode())) {// 股份 都由1号开票设备开
            deviceCondition.put("sourceDoc", "1");
        }
        postData.put("deviceCondition", deviceCondition);
        // edited by shenyouyi 2020-10-26 18:59:01
        // orgcode 从 invoiceorgcode中获取
        // postData.put("orgcode", pmInvoiceApplyEntity.getOrgcode());
        postData.put("orgcode", pmInvoiceApplyEntity.getInvoiceorgcode());
        postData.put("deptcode", pmInvoiceApplyEntity.getDeptcode());
        postData.put("usercode", pmInvoiceApplyEntity.getUsercode());
        postData.put("username", pmInvoiceApplyEntity.getUsername());
        postData.put("buyername", pmInvoiceApplyEntity.getCompanyname());
        //将erp单号推到开票平台
        postData.put("erpSoDocNo",pmInvoiceApplyEntity.getErpdocno());
        // edited by shenyouyi 2020-10-17 14:30:57
        // 税号去除空格
        String taxno = pmInvoiceApplyEntity.getTaxno();
        if(!StringUtil.isEmpty(taxno)){
            taxno = taxno.replace(" ","");
        }
        postData.put("buyertaxno", taxno);
        postData.put("buyeraddresstel", pmInvoiceApplyEntity.getCompanyaddress() + " " + pmInvoiceApplyEntity.getCompanytel());
        postData.put("buyerbank", pmInvoiceApplyEntity.getBankname() + " " + pmInvoiceApplyEntity.getBankaccount());
        postData.put("receivername", pmInvoiceApplyEntity.getReceiver());
        postData.put("receivermobile", pmInvoiceApplyEntity.getReceivertel());
        postData.put("receiveraddress", pmInvoiceApplyEntity.getMailaddress());
        postData.put("description", pmInvoiceApplyEntity.getDescription());
        List<Map<String, Object>> lines = new ArrayList<>();
        Map<String, Object> line = new HashMap<>();
        line.put("name", pmInvoiceApplyEntity.getInvoicename());
        // edited by shenyouyi 2020-11-06 14:42:14
        // 页面上可以填写 单位、数量、单价
        line.put("unit", pmInvoiceApplyEntity.getInvoiceunit());
        line.put("count", pmInvoiceApplyEntity.getInvoicecount());
        line.put("amount", pmInvoiceApplyEntity.getInvoiceamount());
        /*line.put("count", 1);
        line.put("amount", pmInvoiceApplyEntity.getInvoicemoney());*/
        line.put("totalamount", pmInvoiceApplyEntity.getInvoicemoney());
        // 设置税率
        BigDecimal taxrate = BigDecimal.ZERO;
        int percentIndex = invoicetypeDesc.indexOf("%");
        if (percentIndex > -1) {
            taxrate = new BigDecimal(invoicetypeDesc.substring(0, percentIndex)).divide(new BigDecimal("100"));
        }
        line.put("taxrate", taxrate);
        // 信息技术服务的编码
        String goodscode = pmInvoiceApplyEntity.getExplain();
        if(StringUtil.isEmpty(goodscode)){
            goodscode = "3040203";
        }
        line.put("goodscode", goodscode);
        lines.add(line);
        postData.put("lines", lines);
        // 两个系统的编码不一致一致，都是
        String doctype = pmInvoiceApplyEntity.getCategory();
        if ("2".equals(doctype)) {// pm中的作废，对应发票系统中的3--作废
            doctype = "3";
        } else if ("3".equals(doctype)) {// pm中的重开，对应发票系统中的2--作废重开
            doctype = "2";
        }
        postData.put("doctype", doctype);
        // 作废重开原因
        String reinvoicereason = pmInvoiceApplyEntity.getReinvoicereason();
        if (!StringUtil.isEmpty(reinvoicereason)) {
            postData.put("cancelReOpenReason", reinvoicereason);
        }
        // 原发票号
        String oldinvoicecode = pmInvoiceApplyEntity.getOldinvoicecode();
        if (!StringUtil.isEmpty(oldinvoicecode)) {
            postData.put("oldBillNo", oldinvoicecode);
        }
        // 原发票金额
        BigDecimal oldinvoicemoney = pmInvoiceApplyEntity.getOldinvoicemoney();
        if (oldinvoicemoney != null) {
            postData.put("oldBillMoney", oldinvoicemoney);
        }
        // 发票特殊要求
        String demand = pmInvoiceApplyEntity.getDemand();
        if (!StringUtil.isEmpty(demand)) {
            postData.put("specialrequirements", demand);
        }
        // 作废发票邮寄地址 -- 作废和作废重开是需要，此字段后期添加
        String cancelbilllogisticsinfo = pmInvoiceApplyEntity.getCancelbilllogisticsinfo();
        if (!StringUtil.isEmpty(cancelbilllogisticsinfo)) {
            postData.put("cancelbilllogisticsinfo", cancelbilllogisticsinfo);
        }
        // 是否发送快递 -- 新增 和 作废重开需要，此字段后期添加
        int sendflag = pmInvoiceApplyEntity.getSendflag();
        postData.put("sendFlag", sendflag);
        // ERP销售订单号 erpSoDocNo 这里没有传空字符串
        //String erpcode = "";
        //postData.put("erpSoDocNo", erpcode);
        return postData;
    }

    /**
     * @return
     * @author: shenyouyi
     * @date: 2020-09-25
     * @description: 作废发票信息
     * @modify:
     */
    @Transactional
    public void cancelInvoiceRecord(ITapService service, TapEntity entity) {
        // 将发票记录修改为已作废
        CboApprovalNodeInsEntity nodeIns = (CboApprovalNodeInsEntity) entity;
        String sourceId = ConvertUtil.convertToString(nodeIns.getSourceid());
        PmInvoiceApplyService pmInvoiceApplyService = (PmInvoiceApplyService) SpringUtil.getBean("pmInvoiceApplyService");
        PmInvoiceApplyEntity pmInvoiceApplyEntity = pmInvoiceApplyService.queryById(sourceId);
        String oldinvoicecode = pmInvoiceApplyEntity.getOldinvoicecode();
        PmInvoiceRecordService pmInvoiceRecordService = (PmInvoiceRecordService) SpringUtil.getBean("pmInvoiceRecordService");
        pmInvoiceRecordService.setInvoiceState(pmInvoiceApplyEntity.getOldid(), oldinvoicecode, PmSystemConst.InvoiceCancelStatusEnum.Canceled);
    }
}
